from turtle import pos
from typing import Dict, List, Optional, Any
from datetime import datetime

from vnpy.trader.constant import Direction, Offset
from portfolio_trader.engine.position_manager import PositionManager
from portfolio_trader.signal.signal_generator import SignalGenerator
from portfolio_trader.signal.signal_result import SignalResult
from portfolio_trader.datafeed.data_loader import PortfolioDataLoader


class SignalManager:
    """量化信号管理器"""
    
    def __init__(self, position_manager: Optional[PositionManager] = None):
        """初始化"""
        self.signal_generator = SignalGenerator()
        self.position_manager = position_manager
        self.signals: Dict[str, Dict[str, List[SignalResult]]] = {}  # symbol: {strategy: signal_list}
        self.data_loader = PortfolioDataLoader()
        
    def init(self, tushare_token: str) -> bool:
        """初始化Tushare token"""
        return self.signal_generator.data_loader.init(tushare_token)
    
    def generate_signals_for_portfolio(self, strategy_name: str = "BollChannel", days: int = 30) -> Dict[str, List[SignalResult]]:
        """为投资组合生成交易信号
        
        参数:
            strategy_name (str): 策略名称
            days (int): 回溯天数
            
        返回:
            Dict[str, List[SignalResult]]: 股票代码到信号列表的映射
        """
        if not self.position_manager:
            print("未设置持仓管理器，无法获取持仓股票")
            return {}
        
        # 获取持仓股票
        positions = self.position_manager.get_positions()
        symbols = [pos for pos in positions.keys()]
        # print(symbols)
        
        # 生成信号
        signals = self.signal_generator.generate_portfolio_signals(symbols, strategy_name, days)
        
        # 保存信号
        for symbol, signal_list in signals.items():
            if symbol not in self.signals:
                self.signals[symbol] = {}
            self.signals[symbol][strategy_name] = signal_list
        
        return signals
    
    def get_latest_signals_for_portfolio(self, strategy_name: str = "BollChannel") -> Dict[str, SignalResult]:
        """获取投资组合的最新交易信号
        
        参数:
            strategy_name (str): 策略名称
            
        返回:
            Dict[str, SignalResult]: 股票代码到最新信号的映射
        """
        if not self.position_manager:
            print("未设置持仓管理器，无法获取持仓股票")
            return {}
        
        # 获取持仓股票
        positions = self.position_manager.get_positions()
        symbols = [pos for pos in positions.keys()]
        
        # 获取最新信号
        return self.signal_generator.get_latest_signals(symbols, strategy_name)
    
    def get_signal_summary(self, strategy_name: str = "BollChannel") -> Dict[str, Dict]:
        """
        获取最新信号摘要
        
        参数:
            strategy_name (str): 策略名称
            
        返回:
            Dict[str, Dict]: 股票代码到信号摘要的映射
        """
        latest_signals = self.get_latest_signals_for_portfolio(strategy_name)
        result = {}
        
        for symbol, signal in latest_signals.items():
            # 直接使用signal的to_dict方法获取信号摘要
            result[symbol] = signal.to_dict()
            
        return result
    
    def get_latest_trading_day_signals(self, strategy_names: List[str] = None) -> Dict[str, Dict[str, Dict[str, Any]]]:
        """获取最近交易日的所有策略信号
        
        参数:
            strategy_names (List[str]): 策略名称列表，如果为None则使用所有可用策略
            
        返回:
            Dict[str, Dict[str, Dict[str, Any]]]: 以JSON结构返回的信号数据
            格式为 {symbol: {strategy_name: signal_dict}}
        """
        if not self.position_manager:
            print("未设置持仓管理器，无法获取持仓股票")
            return {}
        
        # 获取持仓股票
        positions = self.position_manager.get_positions()
        symbols = [pos for pos in positions.keys()]
        
        if not symbols:
            print("当前没有持仓股票")
            return {}
        
        # 如果未指定策略，使用所有可用策略
        if not strategy_names:
            strategy_names = list(self.signal_generator.strategy_classes.keys())
        
        # 获取最近的交易日期
        latest_trading_day = None
        for symbol in symbols:
            latest_bar = self.data_loader.get_latest_daily_data(symbol)
            if latest_bar:
                if latest_trading_day is None or latest_bar.datetime > latest_trading_day:
                    latest_trading_day = latest_bar.datetime
                break
        
        if not latest_trading_day:
            print("无法获取最近交易日")
            return {}
        
        print(f"最近交易日: {latest_trading_day}")
        
        # 生成所有策略的信号
        result = {}
        for symbol in symbols:
            result[symbol] = {}
            for strategy_name in strategy_names:
                # 生成信号
                signals = self.signal_generator.generate_signal(symbol, strategy_name)
                
                # 筛选出最近交易日的信号
                latest_day_signals = []
                for signal in signals:
                    if signal.datetime.date() == latest_trading_day.date():
                        latest_day_signals.append(signal)
                
                if latest_day_signals:
                    # 按时间排序，获取最新的信号
                    sorted_signals = sorted(latest_day_signals, key=lambda x: x.datetime, reverse=True)
                    result[symbol][strategy_name] = sorted_signals[0].to_dict()
                else:
                    # 创建一个持仓信号
                    hold_signal = SignalResult(symbol, strategy_name)
                    hold_signal.datetime = latest_trading_day
                    hold_signal.set_hold_signal()
                    result[symbol][strategy_name] = hold_signal.to_dict()
        
        return result